//
//  GradientCircleLayer.m
//  GraintCircleView
//
//  Created by huangwenchen on 15/4/24.
//  Copyright (c) 2015年 huangwenchen. All rights reserved.
//

#import "GradientCircleLayer.h"

@interface GradientCircleLayer() <CAAnimationDelegate>
@property (assign, nonatomic) CGFloat progress;
@property (strong, nonatomic) CAShapeLayer* shapePlayer;
@property (strong, nonatomic) CAShapeLayer* shapeBackPlayer;
@end

#define pi 3.14159265359  
#define   DEGREES_TO_RADIANS(degrees)  ((pi * degrees)/ 180)  
@implementation GradientCircleLayer
{
    CGFloat _beginFixed;
}

- (instancetype)initWithFrame:(CGRect)rect
                    fromColor:(UIColor *)fromColor
                           to:(UIColor *)toColor
                    lineWidth:(CGFloat)width {
    if (self = [self initGraintCircleWithBounds:CGRectMake(rect.size.width / 2 + rect.origin.x, rect.size.height / 2 + rect.origin.y, rect.size.width, rect.size.height) position:CGPointZero fromColor:fromColor toColor:toColor lineWidth:width]) {

    }
    return self;
}
-(instancetype)initGraintCircleWithBounds:(CGRect)bounds
                                 position:(CGPoint)position
                                fromColor:(UIColor *)fromColor
                                  toColor:(UIColor *)toColor
                                lineWidth:(CGFloat) linewidth {
    return [self initGraintCircleWithBounds:bounds position:position fromColor:fromColor toColor:toColor lineWidth:linewidth beginPointOffset:0.135 endPointOffset:0];
}
-(instancetype)initGraintCircleWithBounds:(CGRect)bounds
                                 position:(CGPoint)position
                                fromColor:(UIColor *)fromColor
                                  toColor:(UIColor *)toColor
                                lineWidth:(CGFloat) linewidth
                         beginPointOffset:(CGFloat)beginPointOffset endPointOffset:(CGFloat)endPointOffset{
    if (self = [super init]) {
//        [self setNeedsDisplay];
        self.frame = bounds;
        _beginFixed = 0;
        self.beginPointOffset = beginPointOffset;
        self.endPointOffset = endPointOffset;
        self.progress = 0;
        self.bounds = bounds;
        self.position = position;
        NSArray * colors = [self graintFromColor:fromColor toColor:toColor count:4.0];
        for (int i = 0; i < colors.count -1; i++) {
            CAGradientLayer * graint = [CAGradientLayer layer];
            graint.bounds = CGRectMake(0,0,CGRectGetWidth(bounds)/2,CGRectGetHeight(bounds)/2);
            NSValue * valuePoint = [[self positionArrayWithMainBounds:self.bounds] objectAtIndex:i];
            graint.position = valuePoint.CGPointValue;
            UIColor * fromColor = colors[i];
            UIColor * toColor = colors[i+1];
            NSArray *colors = [NSArray arrayWithObjects:(id)fromColor.CGColor, toColor.CGColor, nil];
            NSNumber *stopOne = [NSNumber numberWithFloat:0.0];
            NSNumber *stopTwo = [NSNumber numberWithFloat:1.0];
            NSArray *locations = [NSArray arrayWithObjects:stopOne, stopTwo, nil];
            graint.colors = colors;
            graint.locations = locations;
            graint.startPoint = ((NSValue *)[[self startPoints] objectAtIndex:i]).CGPointValue;
            graint.endPoint = ((NSValue *)[[self endPoints] objectAtIndex:i]).CGPointValue;
            [self addSublayer:graint];
            //Set mask
            CAShapeLayer * shapelayer = [CAShapeLayer layer];
            self.shapePlayer = shapelayer;
            CGRect rect = CGRectMake(0,0,CGRectGetWidth(self.bounds) - 2 * linewidth, CGRectGetHeight(self.bounds) - 2 * linewidth);
            shapelayer.bounds = rect;
            shapelayer.position = CGPointMake(CGRectGetWidth(self.bounds)/2, CGRectGetHeight(self.bounds)/2);
            shapelayer.strokeColor = [UIColor blueColor].CGColor;
            shapelayer.fillColor = [UIColor clearColor].CGColor;
            UIBezierPath *aPath = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:CGRectGetWidth(rect)/2];
            shapelayer.path = aPath.CGPath;
            shapelayer.lineWidth = linewidth;
            shapelayer.lineCap = kCALineCapSquare;
            shapelayer.strokeStart = _beginFixed + _beginPointOffset;
            shapelayer.strokeEnd = _beginFixed + _beginPointOffset;
//            shapelayer.strokeEnd = self.progress;
            [self setMask:shapelayer];
            self.transform = CATransform3DMakeRotation(M_PI_2*2, 0, 0, 1);
        }
    }
    return self;
}


//- (void)display {
//    // 设置音量值为合适的音量插值
//    [CATransaction begin];
//    [CATransaction setDisableActions: YES];
//    CGFloat fP = [self.presentationLayer progress] * 0.97 + 0.015;
//    self.shapePlayer.strokeEnd = fP;
//    [CATransaction commit];
//    
//}
//
//+ (BOOL)needsDisplayForKey:(NSString *)key {
//    if([key isEqualToString:@"progress"]){
//        return  YES;
//    }
//    return [super needsDisplayForKey:key];
//}

- (void)animateCircleWithValue:(CGFloat)progress beginTime:(NSTimeInterval)beginTime{  
    CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];  
    anim.duration = 0.6;  
    anim.fillMode = kCAFillModeForwards;  
    anim.removedOnCompletion = NO;  
//    anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    anim.delegate = self;  
    anim.fromValue = @([self uiProgressWIthProgress:self.progress]);
    anim.beginTime = beginTime;
    anim.toValue =@(progress);
    self.progress = progress;
    [self.shapePlayer addAnimation:anim forKey:@(beginTime).stringValue];  
}  

- (void)addProgress:(CGFloat)progress animated:(BOOL)animated {
    if (animated) {
        [self addAnimationWithProgress:progress];
    } else {
        self.progress = progress;
        self.shapePlayer.strokeEnd = [self uiProgressWIthProgress:progress];
    }
}

- (void)addAnimationWithProgress:(CGFloat)progress {
    CGFloat value = MIN(progress, 1);
    [self addAnimationWithValuesArray:@[@(value)] beginTimes:@[@0]];
}

- (void)addAnimationWithValuesArray:(NSArray<NSNumber *> *)values beginTimes:(NSArray<NSNumber *> *)beginTimes {
    int i = 0;
    self.progress = [self actualProgressWIthProgress:self.shapePlayer.strokeEnd];
    for (NSNumber *value in values) {
        NSTimeInterval beginTime = beginTimes[i].integerValue;
        CABasicAnimation *anim = [self animationWithBeginTime:beginTime toValue:value.floatValue];
        self.progress = value.floatValue;
        [self.shapePlayer addAnimation:anim forKey: @(i).stringValue];
        i++;
    }
    
//    CABasicAnimation *anim1 = [self animationWithBeginTime:0.5 toValue:0.1];
//    CABasicAnimation *anim2 = [self animationWithBeginTime:1.5 toValue:0.6];
//    [self.shapePlayer addAnimation:anim1 forKey: @""];
//    [self.shapePlayer addAnimation:anim2 forKey: @""];
}

- (CABasicAnimation *)animationWithBeginTime:(NSTimeInterval)beginTime toValue:(CGFloat)value {
    CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];  
    anim.duration = 0.9;  
    anim.fillMode = kCAFillModeForwards;  
    anim.removedOnCompletion = NO;  
    //    anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    anim.delegate = self;  
    anim.fromValue = @([self uiProgressWIthProgress:self.progress]);
    anim.beginTime = CACurrentMediaTime() + beginTime;
    anim.toValue =@([self uiProgressWIthProgress:value]);
//    anim.keyPath = @(beginTime).stringValue;
//    self.progress = value;
    return anim;
}

- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag {
    CABasicAnimation *ani = (id)anim;
    [self.shapePlayer removeAnimationForKey:ani.keyPath];  
    self.shapePlayer.strokeEnd = [ani.toValue floatValue] ;
    [self setNeedsDisplay];  
}

- (CGFloat)uiProgressWIthProgress:(CGFloat)progress {
    CGFloat final = self.beginPointOffset + progress * (1 - self.beginPointOffset*2) + 0.008;
    return final;
//    return _beginFixed + (1 - self.beginPointOffset - _beginFixed * 2) * progress;
}

- (CGFloat)actualProgressWIthProgress:(CGFloat)progress {
    CGFloat final = (progress - self.beginPointOffset - 0.008)/(1 - self.beginPointOffset*2);
    return final;
//    return (progress - _beginFixed) / (1 - self.beginPointOffset - _beginFixed * 2);
}

- (id<CAAction>)actionForKey:(NSString *)event {
    if ([self presentationLayer] != nil) {
        if ([event isEqualToString:@"progress"]) {
            CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:event];
            anim.fromValue = [[self presentationLayer] valueForKey:event];
//            anim.fromValue = @(self.shapePlayer.strokeEnd);
            return anim;
        }
    }
    return [super actionForKey:event];
}


+(instancetype)layerWithWithBounds:(CGRect)bounds
                          Position:(CGPoint)position
                         FromColor:(UIColor *)fromColor
                           ToColor:(UIColor *)toColor
                         LineWidth:(CGFloat)linewidth{
    GradientCircleLayer * layer = [[self alloc] initGraintCircleWithBounds:bounds
                                                                  position:position
                                                                 fromColor:fromColor
                                                                   toColor:toColor
                                                                 lineWidth:linewidth];
    return layer;
}
-(NSArray *)positionArrayWithMainBounds:(CGRect)bounds{
    CGPoint first = CGPointMake(CGRectGetWidth(bounds)/4 *3, CGRectGetHeight(bounds)/4 *1);
    CGPoint second = CGPointMake(CGRectGetWidth(bounds)/4 *3, CGRectGetHeight(bounds)/4 *3);
    CGPoint thrid = CGPointMake(CGRectGetWidth(bounds)/4 *1, CGRectGetHeight(bounds)/4 *3);
    CGPoint fourth = CGPointMake(CGRectGetWidth(bounds)/4 *1, CGRectGetHeight(bounds)/4 *1);
    return @[[NSValue valueWithCGPoint:first],
             [NSValue valueWithCGPoint:second],
             [NSValue valueWithCGPoint:thrid],
             [NSValue valueWithCGPoint:fourth]];
}
-(NSArray *)startPoints{
    return @[[NSValue valueWithCGPoint:CGPointMake(0,0)],
             [NSValue valueWithCGPoint:CGPointMake(1,0)],
             [NSValue valueWithCGPoint:CGPointMake(1,1)],
             [NSValue valueWithCGPoint:CGPointMake(0,1)]];
}
-(NSArray *)endPoints{
    return @[[NSValue valueWithCGPoint:CGPointMake(1,1)],
             [NSValue valueWithCGPoint:CGPointMake(0,1)],
             [NSValue valueWithCGPoint:CGPointMake(0,0)],
             [NSValue valueWithCGPoint:CGPointMake(1,0)]];
}
-(NSArray *)graintFromColor:(UIColor *)fromColor toColor:(UIColor *)toColor count:(NSInteger)count{
    CGFloat fromR = 0.0,fromG = 0.0,fromB = 0.0,fromAlpha = 0.0;
    [fromColor getRed:&fromR green:&fromG blue:&fromB alpha:&fromAlpha];
    CGFloat toR = 0.0,toG = 0.0,toB = 0.0,toAlpha = 0.0;
    [toColor getRed:&toR green:&toG blue:&toB alpha:&toAlpha];
    NSMutableArray * result = [[NSMutableArray alloc] init];
    for (int i = 0; i <= count; i++) {
        CGFloat oneR = fromR + (toR - fromR)/count * i;
        CGFloat oneG = fromG + (toG - fromG)/count * i;
        CGFloat oneB = fromB + (toB - fromB)/count * i;
        CGFloat oneAlpha = fromAlpha + (toAlpha - fromAlpha)/count * i;
        UIColor * onecolor = [UIColor colorWithRed:oneR green:oneG blue:oneB alpha:oneAlpha];
        [result addObject:onecolor];
    }
    return result;
}
-(UIColor *)midColorWithFromColor:(UIColor *)fromColor toColor:(UIColor*)toColor progress:(CGFloat)progress{
    CGFloat fromR = 0.0,fromG = 0.0,fromB = 0.0,fromAlpha = 0.0;
    [fromColor getRed:&fromR green:&fromG blue:&fromB alpha:&fromAlpha];
    CGFloat toR = 0.0,toG = 0.0,toB = 0.0,toAlpha = 0.0;
    [toColor getRed:&toR green:&toG blue:&toB alpha:&toAlpha];
    CGFloat oneR = fromR + (toR - fromR) * progress;
    CGFloat oneG = fromG + (toG - fromG) * progress;
    CGFloat oneB = fromB + (toB - fromB) * progress;
    CGFloat oneAlpha = fromAlpha + (toAlpha - fromAlpha) * progress;
    UIColor * onecolor = [UIColor colorWithRed:oneR green:oneG blue:oneB alpha:oneAlpha];
    return onecolor;
}


@end
